package com.example.rbacmanage.service.app.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.example.rbacmanage.common.Constant;
import com.example.rbacmanage.common.Result;
import com.example.rbacmanage.common.enums.UploadTypeEnum;
import com.example.rbacmanage.entity.app.AppUser;
import com.example.rbacmanage.entity.app.MinAppConfig;
import com.example.rbacmanage.mapper.app.AppUserMapper;
import com.example.rbacmanage.mapper.app.MinAppConfigMapper;
import com.example.rbacmanage.property.DefinedProperty;
import com.example.rbacmanage.service.app.AppUserService;
import com.example.rbacmanage.service.system.UploadFileService;
import com.example.rbacmanage.util.FileUtils;
import com.example.rbacmanage.util.HttpClientUtil;
import com.example.rbacmanage.util.JwtTokenUtil;
import com.example.rbacmanage.util.WxUtil;
import com.example.rbacmanage.vo.WxLoginReq;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AppUserServiceImpl implements AppUserService {
    @Autowired
    private AppUserMapper appUserMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private MinAppConfigMapper minAppConfigMapper;
    @Autowired
    private UploadFileService uploadFileService;

    //应用id
    @Value("${minapp.appId}")
    private String appId;
    //应用秘钥
    @Value("${minapp.appSecret}")
    private String appSecret;

    @Override
    public void save(AppUser o) {
        if(!StringUtils.isEmpty(o.getPassword())){
            String passworddecode = passwordEncoder.encode(o.getPassword());
            o.setPassword(passworddecode);
        }
        appUserMapper.insert(o);
    }

    @Override
    public void remove(Long[] ids) {
        for(Long id:ids){
            appUserMapper.del(id);
        }
    }

    @Override
    public void update(AppUser o) {
        if(!StringUtils.isEmpty(o.getPassword())){
            String passworddecode = passwordEncoder.encode(o.getPassword());
            o.setPassword(passworddecode);
        }
        appUserMapper.update(o);
    }

    @Override
    public List<AppUser> getAll(AppUser appUser) {
        return appUserMapper.list(appUser);
    }

    @Override
    public PageInfo<AppUser> getPage(AppUser o) {
        PageHelper.startPage(o.getPage(), o.getLimit());
        return new PageInfo<>(appUserMapper.list(o));
    }

    @Override
    public AppUser getById(Long id) {
        AppUser appUser = appUserMapper.queryOneById(id);
        if (appUser == null){
            return appUser;
        }
        return appUser;
    }

    @Override
    public Integer getCount(AppUser appUser) {
        return 0;
    }

    @Override
    public String login(AppUser appUser){
        String token = JwtTokenUtil.generateToken(appUser.getId()+"");
        Date expireDate=JwtTokenUtil.getExpiredDateFromToken(token);
        redisTemplate.opsForValue().set(Constant.appLoginUserToken+ appUser.getId(),token,expireDate.getTime(), TimeUnit.MILLISECONDS);
        return token;
    }

    @Override
    public String register(AppUser appUserReq) {
        String passworddecode = passwordEncoder.encode(appUserReq.getPassword());
        AppUser appUser = new AppUser();
        appUser.setUserName(appUserReq.getUserName());
        appUser.setPassword(passworddecode);
        appUser.setEmail(appUserReq.getEmail());
        appUser.setPhone(appUserReq.getPhone());
        appUser.setCreateTime(new Date());
        appUser.setUpdateTime(new Date());
        appUser.setBriefIntroduction(appUserReq.getBriefIntroduction());
        appUser.setEmailValidCode(appUserReq.getEmailValidCode());
        appUserMapper.insert(appUser);
        return "注册成功";
    }

    @Override
    public Boolean logout(Long userId) {
        String token = (String) redisTemplate.opsForValue().get(Constant.appLoginUserToken+userId);
        //刷新token
        String tokenNew = JwtTokenUtil.refreshToken(token);
        Date expireDate=JwtTokenUtil.getExpiredDateFromToken(tokenNew);
        redisTemplate.opsForValue().set(Constant.appLoginUserToken+userId,tokenNew,expireDate.getTime(), TimeUnit.MILLISECONDS);
        return true;
    }

    @Override
    public AppUser getByPhone(String phone) {
        return appUserMapper.queryOneByUsername(phone);
    }

    @Override
    public Result wxLogin(WxLoginReq wxLoginReq) {
        MultipartFile file = FileUtils.convert(wxLoginReq.getAvatar(),System.currentTimeMillis()+".jpeg");
        AppUser appUser = new AppUser();
        appUser.setNickName(wxLoginReq.getNickName());
        try {
            if(file != null){
                // 上传并返回新文件名称
                String filePath = uploadFileService.uploadFile(UploadTypeEnum.LOCALUPLOAD.getType(),file);
                appUser.setAvatar(filePath);
            }
            MinAppConfig minAppConfig=minAppConfigMapper.selectByShopIdAndType(wxLoginReq.getShopId(),"0");
            String accessToken = WxUtil.getAccessToken(minAppConfig.getAppId(),minAppConfig.getAppSecret(),false);
            //获取openid
            if (!StringUtils.isEmpty(wxLoginReq.getWxCode())){
                WxMaService wxMaService = WxUtil.getWxMaService(minAppConfig.getAppId(),minAppConfig.getAppSecret(),accessToken,null,null);
                WxMaJscode2SessionResult result = wxMaService.jsCode2SessionInfo(wxLoginReq.getWxCode());
                String sessionKey = result.getSessionKey();
                String openid = result.getOpenid();
                appUser.setOpenId(openid);
            }
            //获取手机号
            if (!StringUtils.isEmpty(wxLoginReq.getPhoneCode())){
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("code",wxLoginReq.getPhoneCode());
                String reqParam = jsonObject.toString();
                String result = HttpClientUtil.doPostJsonReturnString("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+accessToken,reqParam,null);
                com.alibaba.fastjson.JSONObject object = JSON.parseObject(result);
                if (object.getString("errcode").equals("42001")){
                    accessToken = WxUtil.getAccessToken(minAppConfig.getAppId(),minAppConfig.getAppSecret(),true);
                    result = HttpClientUtil.doPostJsonReturnString("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+accessToken,reqParam,null);
                    object = JSON.parseObject(result);
                }
                com.alibaba.fastjson.JSONObject phonenumber = object.getJSONObject("phone_info");
                appUser.setPhone(phonenumber.getString("phoneNumber"));
            }
            //判断手机号或者openid是否存在用户
            AppUser query = new AppUser();
            query.setOpenId(appUser.getOpenId());
            query.setPhone(appUser.getPhone());
            Integer count = appUserMapper.countByOpenIdOrPhone(query.getOpenId(),query.getPhone());
            if (count == null || count == 0) {
                appUser.setCreateTime(new Date());
                appUserMapper.insert(appUser);
            }else{
                appUser.setUpdateTime(new Date());
                AppUser user = appUserMapper.queryOneByUsername(appUser.getOpenId());
                appUser.setId(user.getId());
                appUserMapper.update(appUser);
            }
            String token = login(appUser);
            Map<String,Object> map = new HashMap<>();
            map.put("result",token);
            map.put("expiredTime", JwtTokenUtil.getExpiredDateFromToken(token));
            return Result.success(map);
        } catch (Exception e) {
        }
        return Result.error("登录失败");
    }
}
